<!DOCTYPE html>
<html lang="zh-cn">
  <head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta name="author" content="Zhou Wei <zromyk@163.com>">
  <title>C++设计模式</title>
  <link rel="shortcut icon" href="/favicon.ico">
  <link rel="stylesheet" href="/style/html/pure.css">
  <link rel="stylesheet" href="/style/html/main.css">
  <link rel="stylesheet" href="https://cdn.staticfile.org/font-awesome/4.7.0/css/font-awesome.css">
  <!-- <link rel="stylesheet" href="https://apps.bdimg.com/libs/highlight.js/9.1.0/styles/default.min.css"> -->
<link rel="stylesheet" href="/style/article/highlight/default.min.css">
<link rel="stylesheet" href="/style/article/pell-1.0.6/dist/pell.css">

</head>
<body>
  <div id="menu-background"></div>
  <div id="menu">
    <div class="pure-menu pure-menu-horizontal">
  <ul class="pure-menu-list block-middle">
    <li class="pure-menu-item">
  <a class="pure-menu-heading" href="/index.html">ZROMYK</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" href="/index.html">主页</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" href="/public/archive/index.html">归档</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" href="/public/download/index.html">下载</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" href="/public/feedback/index.html">反馈</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" href="/public/about/index.html">关于我</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" href="https://github.com/zromyk"><i class="fa fa-github" style="font-size:32px"></i></a>
</li>

  </ul>
</div>

  </div>
  <div id="layout">
    <div class="content">
      <div id="nav">
    <div id="navigation" class="navigation">
  <ul class="pure-menu-list">
    <li class="pure-menu-item">
  <a class="pure-menu-link nav2" onclick="animateByNav()" href="#0x00">0x00 工厂模式</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav2" onclick="animateByNav()" href="#0x01">0x01 单例模式</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#1">1. 原始的单例模式</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#_1">使用局部静态对象来解决存在的两个问题</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#2">2. 多线程锁定模式</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#3-dclpdouble-checked-locking-pattern">3. 双重检查锁定模式（DCLP，Double-Checked Locking Pattern）</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#4-best-of-all">4. Best of All</a>
</li>

  </ul>
</div>

</div>
<div id="content-articles">
  <h1 id="C++设计模式" class="content-subhead">C++设计模式</h1>
  <p>
    <span>2021-04-21</span>
    <span><span class="post-category post-category-cpp">C++</span></span>
    <button id="button-markdownEditor" class="pure-button" onclick="markdownEditor()">启用编辑</button>
    <button id="button-save" class="pure-button" onclick="save()">保存</button>
  </p>
  <div id="content-articles-markdownEditor" style="display: none;">
    <h1>编辑 power by pell</h1>
    <div id="editor" class="pell"></div>
    <div style="margin-top:20px;">
        <h3>Text output:</h3>
        <div id="text-output"></div>
    </div>
    <div style="margin-top:20px;">
        <h3>HTML output:</h3>
        <pre id="html-output"></pre>
    </div>
  </div>
  <div id="content-articles-markdown">
    <h2 id="0x00">0x00 工厂模式</h2>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-c++">class Shape { public : void draw(){} };
class Rectangle : public Shape {}
class Square : public Shape {}
class Circle : public Shape {}

class Factory
{
public:
    Shape * getShape(string name) {
        Shape * pShape = nullptr;
        if      (name == &quot;Rectangle&quot;)   { pShape = new Rectangle; }
        else if (name == &quot;Square&quot;)      { pShape = new Square; }
        else if (name == &quot;Circle&quot;)      { pShape = new Circle; }
        return pShape;
    }
}

int main()
{
    Factory factory;
    Shape * pShape = factory.getShape();
    pShape-&gt;draw();
    return 0;
}
</code></span></code></pre>
<h2 id="0x01">0x01 单例模式</h2>
<h3 id="1">1. 原始的单例模式</h3>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-c++">// singleton.h
class Singleton
{
public:
    static Singleton *instance();
private:
    static Singleton *pInstance;
    Singleton(){};
    ~Singleton(){};
    Singleton(const Singleton&amp;);
    Singleton&amp; operator=(const Singleton&amp;);
};

// singleton.cpp
Singleton *Singleton::pInstance = nullptr;
Singleton *Singleton::instance()
{
    if (pInstance == nullptr) {
        pInstance = new Singleton;
    }
    return pInstance;
}
</code></span></code></pre>
<h4 id="_1">使用局部静态对象来解决存在的两个问题</h4>
<ol>
<li>刚刚的代码中有两个问题，一个是多线程的情况下可能会出现new两次的情况。</li>
<li>另外一个是程序退出后没有运行析构函数。</li>
</ol>
<h3 id="2">2. 多线程锁定模式</h3>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-c++">// singleton.h
class Singleton
{
public:
    static Singleton *instance();
private:
    static Singleton *pInstance;
    static pthread_mutex_t mutex;
    Singleton(){};
    ~Singleton(){};
    Singleton(const Singleton&amp;);
    Singleton&amp; operator=(const Singleton&amp;);
};

// singleton.cpp
Singleton *Singleton::pInstance = nullptr;
Singleton *Singleton::instance()
{
    pthread_mutex_lock(&amp;mutex);
    if (pInstance == nullptr) {
        pInstance = new Singleton;
    }
    pthread_mutex_unlock(&amp;mutex);
    return pInstance;
}
</code></span></code></pre>
<p>使用mutex以及静态成员来析构单例。该方案的劣处在于锁导致速度慢，效率低。但是至少是正确的，也能在c++11之前的版本使用。</p>
<h3 id="3-dclpdouble-checked-locking-pattern">3. 双重检查锁定模式（DCLP，Double-Checked Locking Pattern）</h3>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-c++">// singleton.cpp
Singleton *Singleton::pInstance = nullptr;
Singleton *Singleton::instance()
{
    if (pInstance == nullptr) {
        pthread_mutex_lock(&amp;mutex);
        if (pInstance == nullptr) {
            pInstance = new Singleton;
        }
        pthread_mutex_unlock(&amp;mutex);
    }
    return pInstance;
}
</code></span></code></pre>
<h3 id="4-best-of-all">4. Best of All</h3>
<p>C++11规定了local static在多线程条件下的初始化行为，要求编译器保证了内部静态变量的线程安全性。在C++11标准下，《Effective C++》提出了一种更优雅的单例模式实现，使用函数内的 local static 对象。</p>
<p>这种方法也被称为Meyers&rsquo; Singleton。C++0x之后该实现是线程安全的，C++0x之前仍需加锁。</p>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-c++">#if __cplusplus &lt; 201103L
    #error should use C++ 11 implementation
#endif

// singleton.cpp
class Singleton
{
public:
    static Singleton&amp; instance();
private:
    Singleton(){};
    ~Singleton(){};
    Singleton(const Singleton&amp;);
    Singleton&amp; operator=(const Singleton&amp;);
};

Singleton&amp; Singleton::instance()
{
    static Singleton instance;
    return instance;
}
</code></span></code></pre>
  </div>
</div>
 
    </div>
  </div>
  <div id="footer-background">
    <div id="footer">
      <div class="legal pure-g">
  <div class="pure-u-1 u-sm-1-2">
    <p class="legal-license"><a href="https://beian.miit.gov.cn/#/Integrated/index">浙ICP备2020038748号</a></p>
  </div>
  <div class="pure-u-1 u-sm-1-2">
    <p class="legal-links"><a href="https://github.com/zromyk">GitHub</a></p>
    <p class="legal-copyright">Copyright © 2021 Wei Zhou. 保留所有权利。</p>
  </div>
</div>
    </div>
  </div>
  <!-- <script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script> -->
  <script src="/style/html/jquery.min.js"></script>
  <script src='/style/article/latex/latest.js?config=TeX-MML-AM_CHTML'></script>
<!-- <script src="https://cdn.geogebra.org/apps/deployggb.js"></script> -->
<script src="/style/article/deployggb.js"></script>
<!-- <script src="https://apps.bdimg.com/libs/highlight.js/9.1.0/highlight.min.js"></script> -->
<script type="text/javascript">
  // 脚本：navigation 随鼠标移动自动变换宽度
  var element = document.getElementById("navigation"); // 获取要操作的元素
  var elementWidth = parseInt(getComputedStyle(element).width);
  var elementLeft = 0;
  var elementRight = 0;
  element.addEventListener('mouseenter', function (event) { // 添加鼠标按下事件的监听器
    elementLeft = element.getBoundingClientRect().left - 10;
    elementRight = element.getBoundingClientRect().left + elementWidth * 3;
    window.addEventListener('mousemove', resize); // 添加全局的鼠标移动事件的监听器
  });

  function resize(event) {
    var minWidth = elementWidth;
    var maxWidth = elementWidth * 2.5;
    // console.log(elementLeft, event.clientX, elementRight, event.clientX - elementLeft + elementWidth / 2);
    if (elementLeft <= event.clientX && event.clientX <= elementRight) {
      var width = event.clientX - elementLeft + elementWidth / 2;
      width = Math.min(width, maxWidth);
      width = Math.max(width, minWidth);
      element.style.width = width + 'px'; // 设置新的宽度样式属性
    }
    else {
      element.style.width = elementWidth + 'px'; // 设置新的宽度样式属性
      stopResize();
    }
  }

  function stopResize() {
    element.style.width = elementWidth + 'px'; // 设置新的宽度样式属性
    // console.log("stopResize", elementLeft, event.clientX, elementRight, event.clientX - elementLeft + elementWidth / 2);
    window.removeEventListener('mousemove', resize); // 移除鼠标移动事件的监听器
  }
</script>
<script src="/style/article/highlight/highlight.min.js"></script>
<script type="text/javascript">
  // 脚本：code语法高亮
  hljs.initHighlightingOnLoad();
</script>
<script>
  function animateByNav() {
    $("html").animate({
        scrollTop: ($(event.target.hash).offset().top - 52)
    }, 300);
  };
</script>
<script src="/style/article/pell-1.0.6/dist/pell.js"></script>
<script>
  // 脚本：自由编辑页面
  var editor = window.pell.init({
    element: document.getElementById('editor'),
    defaultParagraphSeparator: 'p',
    onChange: function(html) {
        document.getElementById('text-output').innerHTML = html
        document.getElementById('html-output').textContent = html
    }
  });

  function markdownEditor() {
    var articles = document.getElementById('content-articles-markdown');
    if (articles.getAttribute("contenteditable") == "true") {
        articles.setAttribute("contenteditable", "false");
        document.getElementById("content-articles-markdownEditor").style.display = "none"; //隐藏
        document.getElementById("button-markdownEditor").innerHTML = "启用编辑";
    } else {
        articles.setAttribute("contenteditable", "true");
        document.getElementById("content-articles-markdownEditor").style.display = ""; //显示
        document.getElementById("button-markdownEditor").innerHTML = "关闭编辑";
    }
  };

  function save() {
      window.alert("保存成功");
  };
</script>

</body>
</html>
